package cn.wenhaha.install.service.impl;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.db.ds.simple.SimpleDataSource;
import cn.hutool.db.sql.SqlExecutor;
import cn.hutool.system.*;
import cn.wenhaha.common.bean.AppInstallFinish;
import cn.wenhaha.common.bean.dto.install.DataSourceDTO;
import cn.wenhaha.common.config.Global;
import cn.wenhaha.common.config.GlobalApp;
import cn.wenhaha.common.utils.YamlUtils;
import cn.wenhaha.common.utils.file.FileUtils;
import cn.wenhaha.install.service.IIndexService;
import cn.wenhaha.install.service.InstallSqlScript;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.SpringApplicationEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

@Service("installIndexService")
@DependsOn("global")
@Slf4j
public class IndexServiceImpl implements IIndexService, ApplicationListener {

    @Autowired
    private Global global;


    private String appPath=System.getProperty("user.dir");

    private YamlUtils yamlUtils;
    @Autowired
    private ApplicationEventPublisher publisher;


    @Override
    public String[][] checkDir() {

        //判断该目录下是否可读写
        File file = new File(appPath);
        String authority="读写";
        if (!FileUtils.canWrite(file)||!FileUtils.canRead(file)){
            authority="没有读写权限";
        }
        String[][] data={
                {"dir",appPath,"读写",authority,authority.equals("读写")?"ok":"no"}
        };
        return data;
    }

    @Override
    public Map<String, String> checkNnv() {
        HashMap<String, String> dataMap = new HashMap<>();

        RuntimeInfo runtimeInfo = SystemUtil.getRuntimeInfo();
        dataMap.put("JVM剩余空间",getPrintSize(runtimeInfo.getFreeMemory()));
        dataMap.put("JVM最大可用",getPrintSize(runtimeInfo.getUsableMemory()));

        JvmInfo jvmInfo = SystemUtil.getJvmInfo();
        dataMap.put("jvm版本",jvmInfo.getVersion());

        OsInfo osInfo = SystemUtil.getOsInfo();
        dataMap.put("操作系统",osInfo.getName());
        HostInfo hostInfo = SystemUtil.getHostInfo();
        dataMap.put("ip地址",hostInfo.getAddress());

        return dataMap;
    }


    public static String getPrintSize(long size){
        long rest = 0;
        if(size < 1024){
            return String.valueOf(size) + "B";
        }else{
            size /= 1024;
        }

        if(size < 1024){
            return String.valueOf(size) + "KB";
        }else{
            rest = size % 1024;
            size /= 1024;
        }

        if(size < 1024){
            size = size * 100;
            return String.valueOf((size / 100)) + "." + String.valueOf((rest * 100 / 1024 % 100)) + "MB";
        }else{
            size = size * 100 / 1024;
            return String.valueOf((size / 100)) + "." + String.valueOf((size % 100)) + "GB";
        }
    }


    @Override
    public String connectDb(DataSourceDTO dto) {

        String jdbcUrl="jdbc:mysql://{}:{}/{}?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8";
        jdbcUrl=StrUtil.format(jdbcUrl,dto.getHostname(),dto.getHostport(),dto.getDatabase());
        DataSource ds = new SimpleDataSource(jdbcUrl,dto.getUsername(), dto.getPassword());
        Connection connection=null;
        String successMsg="数据库连接成功";
        try {
            connection= ds.getConnection();
            SqlExecutor.call(ds.getConnection(), "select version()");

        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return "数据库连接失败，请检查数据库配置！";
        }finally {
            if (connection!=null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

        }
        try {
            yamlUtils.saveOrUpdateByKey("datasource.link",jdbcUrl);
            yamlUtils.saveOrUpdateByKey("datasource.type",0);
            yamlUtils.saveOrUpdateByKey("datasource.host",dto.getHostname());
            yamlUtils.saveOrUpdateByKey("datasource.port",dto.getHostport());
            yamlUtils.saveOrUpdateByKey("datasource.database",dto.getDatabase());
            yamlUtils.saveOrUpdateByKey("datasource.username",dto.getUsername());
            yamlUtils.saveOrUpdateByKey("datasource.password",dto.getPassword());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return successMsg;
    }

    @Override
    public String install(DataSourceDTO dto) {

        try {

            yamlUtils.saveOrUpdateByKey("app.admin.name",dto.getAccount());
            yamlUtils.saveOrUpdateByKey("app.admin.pwd",dto.getAdminpwd());
            yamlUtils.saveOrUpdateByKey("interface.pass", RandomUtil.randomString(16));
            yamlUtils.saveOrUpdateByKey("site.install_dir",appPath);
         /*   File installSql = new File(appPath + global.getInstall());
            if (!FileUtil.exist(installSql)){ return "安装sql文件丢失!";}
*/
        } catch (IOException e) {
            log.error(e.getMessage());
            return  "配置文件保存失败，请重试!";
        }

        return "系统配置成功，欢迎您使用DS-CMS系统";
    }


    @Override
    public String exSql() {
        String dbType = yamlUtils.getByKey("datasource.type").toString();
        InstallSqlScript sqlScript = null;
        if("0".equals(dbType)){
            sqlScript=new MysqlInstallScript();
        }else {
            sqlScript=new SQLiteInstallScript();
        }

        try {
            sqlScript.execute(yamlUtils);
            yamlUtils.saveOrUpdateByKey("app.cache_flag", SecureUtil.md5(System.currentTimeMillis()+"").substring(0,10));
            GlobalApp.getInstance(true);
            publisher.publishEvent(new AppInstallFinish(true));
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return ExceptionUtil.stacktraceToString(e);
        }
        return  "安装成功";
    }

    @Override
    public String connectSQLite(String dbUri) {
        String jdbcUrl ="jdbc:sqlite:"+dbUri;
        try (Connection connection =DriverManager.getConnection(jdbcUrl)){
            yamlUtils.saveOrUpdateByKey("datasource.link",jdbcUrl);
            yamlUtils.saveOrUpdateByKey("datasource.sqlite",dbUri);
            yamlUtils.saveOrUpdateByKey("datasource.type",1);
       }catch (Exception e){
           e.printStackTrace();
           return e.getMessage();
       }

        return "数据库连接成功";
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof SpringApplicationEvent){
            yamlUtils = new YamlUtils(appPath+global.getConfig());
        }
    }
}
